Clases de objetos 19 y 22 Octubre

Valkyria Chronicles 4

Vimos el trailer del juego Valkyria Chronicles 4 e intentamos hacer algunas clases en base a esto.

Clase Soldado


In [1]:
class Soldier:
    """Clase que representa a un soldado"""

    def __init__(self, name):

        self.name = name

    def get_name(self):
        """Devuelve el nombre del soldado"""
        return self.name

    def __eq__(self,another):
        return self.name == another.name

Pruebas


In [2]:
alicia = Soldier("Alicia Melchiott")
alicia2 = Soldier("Alicia Melchiott")

welkin = Soldier("Welkin Gunther")

assert(alicia.get_name() == "Alicia Melchiott")
assert(welkin.get_name() == "Welkin Gunther")

assert(alicia == alicia)
assert(alicia == alicia2)
assert(alicia != welkin)

Clase Escuadron


In [3]:
class Squad:
    """Clase que representa un escuadron de soldados"""

    def __init__(self, leader):

        self.leader = leader
        self.squad = set()


    def add_soldier(self,soldier):
        """Agrega un soldado al escuadron"""

        if not isinstance(soldier,Soldier):
            raise TypeError("El escuadron solo puede agregar soldados")

        self.squad.add(soldier)

    def kick_soldier(self):
        """Elimina un soldado del escuadron"""

        pass

    def get_soldiers(self):
        """Devuelve todos los soldados del escuadron, formados"""
        
        # soldiers = [ soldier for soldier in self.squad ]
        # soldiers.sort()
        # return soldiers
        return sorted(self.squad)

    def get_soldiers_amount(self):
        """ """
        return len(self.squad)

Pruebas


In [4]:
escuadron = Squad(welkin)

escuadron.add_soldier(alicia)
escuadron.add_soldier(alicia2)

assert(escuadron.get_soldiers_amount()==1)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-cb809c906514> in <module>()
      1 escuadron = Squad(welkin)
      2 
----> 3 escuadron.add_soldier(alicia)
      4 escuadron.add_soldier(alicia2)
      5 

<ipython-input-3-ab9fc9f13c46> in add_soldier(self, soldier)
     14             raise TypeError("El escuadron solo puede agregar soldados")
     15 
---> 16         self.squad.add(soldier)
     17 
     18     def kick_soldier(self):

TypeError: unhashable type: 'Soldier'

Nota de clase

Ayer se nos paso durante la clase notar esto. Tanto los sets como el diccionario necesitan que el objeto tenga definido el metodo magico __hash__ para poder ser utilizados. Podemos pensar que el metodo lo que hace, es devolver "la clave" que representa al objeto. En este caso, por supuestos, podemos asumir que al ser los nombres unicos, podemos usar eso:


In [5]:
class Soldier:
    """Clase que representa a un soldado"""

    def __init__(self, name):

        self.name = name

    def get_name(self):
        """Devuelve el nombre del soldado"""
        return self.name

    def __eq__(self,another):
        return self.name == another.name
    
    def __hash__(self):
        return hash(self.name)

In [6]:
alicia = Soldier("Alicia Melchiott")
alicia2 = Soldier("Alicia Melchiott")

welkin = Soldier("Welkin Gunther")

escuadron = Squad(welkin)

escuadron.add_soldier(alicia)
escuadron.add_soldier(alicia2)

assert(escuadron.get_soldiers_amount()==1)

Clase Arma


In [7]:
class Gun:
    """Clase que representa un arma generica"""
    
    SNIPER = "Sniper"
    MORTAR = "Mortar"
    
    def __init__(self,name,damage,gun_type):
        
        self.name = name
        self.damage = damage
        self.gun_type = gun_type
        
    def attack(self,soldier):
        
        soldier.receive_damage(self.damage,self.gun_type)
        

import random
        
class Soldier:
    """Clase que representa a un soldado"""

    def __init__(self, name,gun):

        self.name = name
        self.gun = gun
        self.hp  =  random.randint(600,1200)
        self.shield = random.randint(1,4)

    def get_name(self):
        """Devuelve el nombre del soldado"""
        return self.name

    def attack(self,enemy):
        """ """
        self.gun.attack(enemy)
        
    def receive_damage(self,damage,gun_type):
        if gun_type == Gun.SNIPER:
            self.hp -= damage / self.shield
            return
        
        self.hp -= damage
        
    def __eq__(self,another):
        return self.name == another.name
    
    def __hash__(self):
        return hash(self.name)

Pruebas


In [8]:
sniper_rifle = Gun("Mk-3",200,Gun.SNIPER)
mortar_launcher = Gun("Elias",700,Gun.MORTAR)

alicia = Soldier("Alicia Melchiott",sniper_rifle)
welkin = Soldier("Welkin Gunther",mortar_launcher)

alicia.attack(welkin)

Omake (La tarea que no hicieron...)


In [9]:
class Calculadora:
    
    def __init__(self):
        
        self.resultado_anterior = 0
        
    def sumar(self,numero_1,numero_2=None):
        """ """
        
        if numero_2 is None:
            numero_2 = self.resultado_anterior
            
        self.resultado_anterior = numero_1 + numero_2
        return self.resultado_anterior
        
    def restar(self,numero_1,numero_2=None):
        """ """
        
        self.resultado_anterior = - self.sumar( - numero_1,numero_2)
        return self.resultado_anterior

Pruebas

Queda para el lector hacer las pruebas y ver si todo funciona como debe (o no)

PD

Armando este notebook me spoilee el final del juego. Mas les vale que aprueben todos el parcial y que el ejercicio de objetos no lo haga mal nadie -.-